function Get-NaNFS {
	<#
	.SYNOPSIS
		Get the status of the NFS Server.
	.DESCRIPTION
		Get the status of the NFS Server.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaNFS
		
		Get the status of the NFS Service.
	.Link
		Enable-NaNFS
		Disable-NaNFS
		Get-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-status")
		try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?) {
			New-Object PSCustomObject  -Property @{
				"Enabled"=(ConvertFrom-NaBool $result."is-enabled");
				"Drained"=(ConvertFrom-NaBool $result."is-drained")
			}
		}
	}
}
function Enable-NaNFS {
	<#
	.SYNOPSIS
		Enables the NFS option. (Effectively the same as the CLI command "nfs on") 
	.DESCRIPTION
		Enables the NFS option. (Effectively the same as the CLI command "nfs on") 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Enable-NaNFS
		
		Enable NFS option
	.Link
		Get-NaNFS
		Disable-NaNFS
		Get-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-enable")
		try {
				$server.InvokeElem($request)| Out-Null
			}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			continue;
		}
	}
}
function Disable-NaNFS {
	<#
	.SYNOPSIS
		Disables  the NFS option. (Effectively the same as the CLI command "nfs on") 
	.DESCRIPTION
		Disables  the NFS option. (Effectively the same as the CLI command "nfs on") 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Disable-NaNFS
		
		Disables the NFS option
	.Link
		Get-NaNFS
		Enable-NaNFS
		Get-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.shouldcontinue("All NFS Exports will be terminated", "Warning")) {
			$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-disable")
			try {
					$server.InvokeElem($request) | out-null
				}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}

function Get-NaExportfs {
	<#
	.SYNOPSIS
		Returns the rules associated with exports, using the new security info 
		structure.
	.DESCRIPTION
		Returns the rules associated with exports, using the new security info 
		structure. If a pathname is specified, the rules associated with the 
		export matching that pathname, are returned; otherwise, rules for all 
		exports are returned.
	.PARAMETER Pathname
		The pathname, for whose matching export, the client wants a listing of 
		the associated rules. If this parameter is provided, the persistent 
		parameter is ignored. 
	.PARAMETER Persistent
		If present, the export entries that are present in the /etc/exports file 
		are returned; otherwise, those loaded in memory are returned. This parameter 
		is ignored, if the pathname parameter is provided. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaExportfs
		
		return all exports loaded in memory on the filer
	.Example
		Get-NaExportfs -Pathname /vol/vol1
		
		return all exports on /vol/vol1
	.OUTPUTS
		NetApp.SDK.NaExportsRule[]
	.Link
		New-NaExportfs
		Set-NaExportfs
		Remove-NaExportfs
		Update-NaExportfs
		Test-NaExportfs
		Enable-NaExportfsFence
		Disable-NaExportfsFence
		Remove-NaExportfsCache
		Get-NaNFSMonitor
	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="Path")] 
	param(
	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="Path")]
	[string]
	$Pathname,

	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="File")]
	[switch]
	$Persistent,

	[Parameter(Position=1,HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-list-rules")
		if ($Pathname){
			$request.AddNewChild("pathname",$Pathname)
		} 
		elseif ($Persistent) {
			$request.AddNewChild("persistent",$true)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?) {
			$result."rules"."exports-rule-info" |? {$_."pathname"} |% {
				[array]$ReadOnly = $_."read-only"."exports-hostname-info" | % {
					switch ($_) {
						{							(ConvertFrom-NaBool $_."all-hosts")} {"All Hosts"; break}
						{							(ConvertFrom-NaBool $_."negate")} {'-{0}' -f $_.name;break}
						{							$_.name} {$_.name}
					}
				}
				[array]$Readwrite = $_."read-write"."exports-hostname-info" | % {
					switch ($_) {
						{							(ConvertFrom-NaBool $_."all-hosts")} {"All Hosts";break}
						{							(ConvertFrom-NaBool $_."negate")} {'-{0}' -f $_.name;break}
						{							$_.name} {$_.name}
					}
				}
				[array]$Root = $_."root"."exports-hostname-info" | % {
					switch ($_) {
						{							(ConvertFrom-NaBool $_."all-hosts")} {"All Hosts";break}
						{							(ConvertFrom-NaBool $_."negate")} {'-{0}' -f $_.name;break}
						{							$_.name} {$_.name}
					}
				}
				[array]$SecFlavor = $_."sec-flavor"."sec-flavor-info"| % {$_.flavor}

				return New-Object NetApp.SDK.NaExportsRule -ArgumentList @(
				$_."pathname",
				$_."actual-pathname",
				$_.anon,
				$_.nosuid,
				$ReadOnly,
				$Readwrite,
				$Root,
				$SecFlavor
				)
			}
		}
	}
}
function New-NaExportfs {
	<#
	.SYNOPSIS
		Enables pathnames for mounting according to the rules specified.
	.DESCRIPTION
		Enables pathnames for mounting according to the rules specified. New rules 
		for the pathnames take effect immediately, ignoring previous rules for 
		specified pathnames. Set the persistent option to save the rule in the 
		etc/exports file and keep the option persistent upon loading or reboot 
	.PARAMETER Pathname
		Directory name or file to export. 
	.PARAMETER ActualPathname
		Pathname inside of the filer which is being exported. The default for 
		this is value in 'pathname'.
	.PARAMETER anon
		All hosts with this user-id or username have root access to this directory
	.PARAMETER nosuid
		If true, causes the server file system to silently ignore any attempt
		to enable the setuid or setgid mode bits. Default value is false. 
	.PARAMETER ReadOnly
		An array of hostnames which only have read privileges.  Enter 'All Hosts' 
		to grant read to all hosts, or precede the hostname with a '-' to indicate 
		an implicide deny.
	.PARAMETER ReadWrite
		An array of hostnames which have read and write privileges. Any hostname in 
		readonly must not be in read-write also. By default, if no 'readonly' or 
		'readwrite' hosts are given, then 'readwrite' contains a hostname of 'all-hosts'.
		precede any hostname with a '-' to indicate an implicide deny.
	.PARAMETER Root
		Array of hostnames which have roots with 'readwrite' or 'readonly' privileges. 
		precede any hostname with a '-' to indicate an implicide deny.
	.PARAMETER SecurityFlavor
		Security flavor information for RPC. Only hosts connecting using the 
		proper security can access the directory. 
	.PARAMETER Persistent
		If present, modifies the etc/exports file to append the rule for a 
		permanent change. (The new rule still takes effect immediately.) 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		New-NaExportfs -Pathname /vol/vol2 -ReadWrite 192.168.1.1/24
		
		Temporaraly Export /vol/vol2 to the 192.168.1.0 subnet.  This export will be 
		removed when either the Update-NaExportfs cmdlets is ran or the filer is 
		rebooted.
	.Example
		New-NaExportfs -Pathname /vol/vol2 -ActualPathname /vol/vol2/old `
			-Root 192.168.1.25 -ReadOnly 192.168.1.26,192.168.1.27 -Persistent
		
		Export /vol/vol2/old as /vol/vol2 granting 192.168.1.25 root access, and 
		readonly access to 192.168.1.26, and 192.1681.27.  These chages are saved 
		to the /etc/exports file, and will persist a reboot
	.OUTPUTS
		NetApp.SDK.NaExportsRule[]
	.Link
		Get-NaExportfs
		Set-NaExportfs
		Remove-NaExportfs
		Update-NaExportfs
		Test-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Pathname,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$ActualPathname,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$anon,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[bool]
	$nosuid,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$ReadOnly,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$ReadWrite,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$Root,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$SecurityFlavor,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[switch]
	$Persistent,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$exportsRuleInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-rule-info")
		$exportsRuleInfo.AddNewChild("pathname",$Pathname)
		if ($anon) {
			$exportsRuleInfo.AddNewChild("anon",$anon)
		}
		if ($nosuid) {
			$exportsRuleInfo.AddNewChild("nosuid",$nosuid)
		}
		if ($ActualPathname) {
			$exportsRuleInfo.AddNewChild("actual-pathname",$ActualPathname)
		}
		if ($ReadOnly) {
			$Read = New-Object Netapp.Manage.NaElement -ArgumentList @("read-only")
			$ReadOnly |%{
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				switch -regex ($_) {
					"^All\sHosts" {$exportsHostnameInfo.AddNewChild('all-hosts', $true);break}
					"^-(?<name>.+)$" {
						$exportsHostnameInfo.AddNewChild('negate', $true)
						$exportsHostnameInfo.AddNewChild('name', $matches.Name)
						break
					}
					"\S+" {$exportsHostnameInfo.AddNewChild('name', $_)}
				}
				$Read.AddChildElement($exportsHostnameInfo)
			}
			$exportsRuleInfo.AddChildElement($Read)
			$msg += "Read-only"
		}
		if ($ReadWrite) {
			$Write = New-Object Netapp.Manage.NaElement -ArgumentList @("read-write")
			$ReadWrite |%{
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				switch -regex ($_) {
					"^All\sHosts" {$exportsHostnameInfo.AddNewChild('all-hosts', $true);break}
					"^-(?<name>.+)$" {
						$exportsHostnameInfo.AddNewChild('negate', $true)
						$exportsHostnameInfo.AddNewChild('name', $matches.Name)
						break
					}
					"\S+" {$exportsHostnameInfo.AddNewChild('name', $_)}
				}
				$Write.AddChildElement($exportsHostnameInfo)
			}
			$exportsRuleInfo.AddChildElement($Write)
			$msg += "Read-write"
		}
		if ($Root) {
			$rt = New-Object Netapp.Manage.NaElement -ArgumentList @("root")
			$Root |%{
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				switch -regex ($_) {
					"^All\sHosts" {$exportsHostnameInfo.AddNewChild('all-hosts', $true);break}
					"^-(?<name>.+)$" {
						$exportsHostnameInfo.AddNewChild('negate', $true)
						$exportsHostnameInfo.AddNewChild('name', $matches.Name)
						break
					}
					"\S+" {$exportsHostnameInfo.AddNewChild('name', $_)}
				}
				$rt.AddChildElement($exportsHostnameInfo)
			}
			$exportsRuleInfo.AddChildElement($rt)
			$msg += "root"
		}
		if ($SecurityFlavor) {
			$secFlavor = New-Object Netapp.Manage.NaElement -ArgumentList @("sec-flavor")
			$SecurityFlavor |%{
				$secFlavorInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("sec-flavor-info")
				$secFlavorInfo.AddNewChild("flavor", $_)
				$secFlavor.AddChildElement($secFlavorInfo)
			}
			$exportsRuleInfo.AddChildElement($secFlavor)
		}
		$rule = New-Object Netapp.Manage.NaElement -ArgumentList @("rules")
		$rule.AddChildElement($exportsRuleInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-append-rules")
		$request.AddChildElement($rule) 

		if ($Persistent) {
			$request.AddNewChild("persistent",$true) 
		}

		if ($pscmdlet.ShouldProcess($Server.Server, "Modifying export $($Pathname) settings")){
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?) {
				Get-NaExportfs -Pathname $Pathname -Server $Server
			}
		}
	}
}
function Set-NaExportfs {
	<#
	.SYNOPSIS
		Sets pathnames for mounting according to the rules specified.
	.DESCRIPTION
		Sets pathnames for mounting according to the rules specified. New rules 
		for the pathnames take effect immediately, ignoring previous rules for 
		specified pathnames. Set the persistent option to save the rule in the 
		etc/exports file and keep the option persistent upon loading or reboot 
		
		***Note you must specify every aspect of the rule the existing rule is 
        rewritten, and any entries left off will be deleted!
	.PARAMETER Pathname
		Directory name or file to export. 
	.PARAMETER ActualPathname
		Pathname inside of the filer which is being exported. The default for 
		this is value in 'pathname'.
	.PARAMETER anon
		All hosts with this user-id or username have root access to this directory
	.PARAMETER nosuid
		If true, causes the server file system to silently ignore any attempt
		to enable the setuid or setgid mode bits. Default value is false. 
	.PARAMETER ReadOnly
		An array of hostnames which only have read privileges.  Enter 'All Hosts' 
		to grant read to all hosts, or precede the hostname with a '-' to indicate 
		an implicide deny.
		
		If No information is provided than any existing exports are removed.
	.PARAMETER ReadWrite
		An array of hostnames which have read and write privileges. Any hostname in 
		readonly must not be in read-write also. By default, if no 'readonly' or 
		'readwrite' hosts are given, then 'readwrite' contains a hostname of 'all-hosts'.
		precede any hostname with a '-' to indicate an implicide deny.
		
		If No information is provided than any existing exports are removed.
	.PARAMETER Root
		Array of hostnames which have roots with 'readwrite' or 'readonly' privileges. 
		precede any hostname with a '-' to indicate an implicide deny.
		
		If No information is provided than any existing exports are removed.
	.PARAMETER SecurityFlavor
		Security flavor information for RPC. Only hosts connecting using the 
		proper security can access the directory. 
	.PARAMETER Persistent
		If present, modifies the etc/exports file to append the rule for a 
		permanent change. (The new rule still takes effect immediately.) 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaExportfs /vol/vol1 | Set-NaExportfs -Root -192.1681.25,192.168.1.0/24
		
		Will overwrite the root exports for /vol/vol1 allowing any host on the 192.168.1.0 subnet
		except 192.168.1.25.
	.OUTPUTS
		NetApp.SDK.NaExportsRule[]
	.Link
		Get-NaExportfs
		New-NaExportfs
		Remove-NaExportfs
		Update-NaExportfs
		Test-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Pathname,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$ActualPathname,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$anon,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[bool]
	$nosuid,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$ReadOnly,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$ReadWrite,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$Root,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[string[]]
	$SecurityFlavor,

	[Parameter(ValueFromPipelineByPropertyName=$TRUE)]
	[switch]
	$Persistent,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$server = (Get-NaServer)
	)
	Process {
		$exportsRuleInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-rule-info")
		$exportsRuleInfo.AddNewChild("pathname",$Pathname)
		if ($anon) {
			$exportsRuleInfo.AddNewChild("anon",$anon)
		}
		if ($nosuid) {
			$exportsRuleInfo.AddNewChild("nosuid",$nosuid)
		}
		if ($ActualPathname) {
			$exportsRuleInfo.AddNewChild("actual-pathname",$ActualPathname)
		}
		if ($ReadOnly) {
			$Read = New-Object Netapp.Manage.NaElement -ArgumentList @("read-only")
			$ReadOnly |%{
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				switch -regex ($_) {
					"^All\sHosts" {$exportsHostnameInfo.AddNewChild('all-hosts', $true);break}
					"^-(?<name>.+)$" {
						$exportsHostnameInfo.AddNewChild('negate', $true)
						$exportsHostnameInfo.AddNewChild('name', $matches.Name)
						break
					}
					"\S+" {$exportsHostnameInfo.AddNewChild('name', $_)}
				}
				$Read.AddChildElement($exportsHostnameInfo)
			}
			$exportsRuleInfo.AddChildElement($Read)
			$msg += "Read-only"
		}
		if ($ReadWrite) {
			$Write = New-Object Netapp.Manage.NaElement -ArgumentList @("read-write")
			$ReadWrite |%{
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				switch -regex ($_) {
					"^All\sHosts" {$exportsHostnameInfo.AddNewChild('all-hosts', $true);break}
					"^-(?<name>.+)$" {
						$exportsHostnameInfo.AddNewChild('negate', $true)
						$exportsHostnameInfo.AddNewChild('name', $matches.Name)
						break
					}
					"\S+" {$exportsHostnameInfo.AddNewChild('name', $_)}
				}
				$Write.AddChildElement($exportsHostnameInfo)
			}
			$exportsRuleInfo.AddChildElement($Write)
			$msg += "Read-write"
		}
		if ($Root) {
			$rt = New-Object Netapp.Manage.NaElement -ArgumentList @("root")
			$Root |%{
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				switch -regex ($_) {
					"^All\sHosts" {$exportsHostnameInfo.AddNewChild('all-hosts', $true);break}
					"^-(?<name>.+)$" {
						$exportsHostnameInfo.AddNewChild('negate', $true)
						$exportsHostnameInfo.AddNewChild('name', $matches.Name)
						break
					}
					"\S+" {$exportsHostnameInfo.AddNewChild('name', $_)}
				}
				$rt.AddChildElement($exportsHostnameInfo)
			}
			$exportsRuleInfo.AddChildElement($rt)
			$msg += "root"
		}
		if ($SecurityFlavor) {
			$secFlavor = New-Object Netapp.Manage.NaElement -ArgumentList @("sec-flavor")
			$SecurityFlavor |%{
				$secFlavorInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("sec-flavor-info")
				$secFlavorInfo.AddNewChild("flavor", $_)
				$secFlavor.AddChildElement($secFlavorInfo)
			}
			$exportsRuleInfo.AddChildElement($secFlavor)
		}
		$rule = New-Object Netapp.Manage.NaElement -ArgumentList @("rule")
		$rule.AddChildElement($exportsRuleInfo)

		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-modify-rule")
		$request.AddChildElement($rule) 

		if ($Persistent) {
			$request.AddNewChild("persistent",$true) 
		}

		if ($pscmdlet.ShouldProcess($Server.Server, "Modifying export $($Pathname) settings")){
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?) {
				Get-NaExportfs -Pathname $Pathname -Server $Server
			}
		}
	}
} 
function Remove-NaExportfs {
	<#
	.SYNOPSIS
		Removes the rules for a set of pathnames. 
	.DESCRIPTION
		Removes the rules for a set of pathnames. This returns an error if any 
		of the pathnames don't have a rule. Set the persistent option to modify 
		the etc/exports file and keep this change persistent upon reboots.
	.PARAMETER Pathname
		Pathnames to be deleted from the exports table. 
	.PARAMETER AllPathnames
		Delete all rules.
	.PARAMETER Persistent
		If present, Modify the etc/exports file to delete the rules permanently. 
		
		CAUTION: If 'AllPathnames' and 'persistent' are both provided, all exports 
		are removed permanently. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Remove-NaExportfs -AllPathnames
		
		Clears all active exports from memory
	.EXAMPLE
		Remove-NaExportfs -Pathname /vol/vol2 -Persistent
		
		Permanently remove any /vol/vol2 exports.		
	.Link
		Get-NaExportfs
		New-NaExportfs
		Set-NaExportfs
		Update-NaExportfs
		Test-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="onepath")] 
	param(
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="onepath")]
	[string]
	$Pathname,

	[Parameter(ParameterSetName="Allpaths")]
	[switch]
	$AllPathnames,

	[Parameter(ParameterSetName="onepath")]
	[Parameter(ParameterSetName="Allpaths")]
	[switch]
	$Persistent,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-delete-rules")
		switch ($PSCmdlet.ParameterSetName)
		{
			"AllPaths"
			{
				if ($Persistent) {
					if ($PSCmdlet.ShouldContinue("You have chosen to PERMANENTLY remove ALL exports!  Do you want to continue?", "CAUTION")) {
						$request.AddNewChild("all-pathnames",$true) 
					} else {
						break
					}

				} 
				else {
					$PSCmdlet.writeWarning("You have chosen to remove all active exports use the Update-NaExportfs cmdlet to reload from /etc/exports.")
					$request.AddNewChild("all-pathnames",$true)
				}
				$msg = "Removing all exports"
			}
			"OnePath"
			{
				$paths = New-Object Netapp.Manage.NaElement -ArgumentList @("pathnames")
				foreach ($p in $Pathname) {
					$pathnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("pathname-info")
					$pathnameInfo.AddNewChild("name",$p) 
					$paths.AddChildElement($pathnameInfo)
				}
				$request.AddChildElement($paths)
				$msg = "Removing exports:'{0}'" -f $Pathname -join ", "
			}
		}
		if ($Persistent) {
			$msg = "PERMANENTLY {0}" -f $msg
			$request.AddNewChild("persistent",$true) 
		}
		if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
function Update-NaExportfs {
	<#
	.SYNOPSIS
		Loads the etc/exports file into memory. Replaces exports rules already 
		residing in memory.
	.DESCRIPTION
		Loads the etc/exports file into memory. Replaces exports rules already 
		residing in memory.
	.PARAMETER Persistent
		Reloads each rule from the exports file and unloads all other rules. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Update-NaExportfs
		
		Reload the /etc/exports file into memory.
	.Link
		Get-NaExportfs
		New-NaExportfs
		Set-NaExportfs
		Remove-NaExportfs
		Test-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="onepath")] 
	param(
	[Parameter()]
	[switch]
	$Persistent,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-load-exports")
		if ($Persistent) {
			$request.AddNewChild("persistent-only",$true) 
		}
		if ($pscmdlet.ShouldProcess($Server.Server, "Reloading /etc/exports into memory")){
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
function Test-NaExportfs {
	<#
	.SYNOPSIS
		Returns true if the host IP has mount permissions for a specified path.
	.DESCRIPTION
		Returns true if the host IP has mount permissions for a specified path.
	.PARAMETER Pathname
		Returns the permissions for this path. 
	.PARAMETER Permission
		Possible values: "ReadOnly", "ReadWrite", and "Root". 
	.PARAMETER IPAddress
		IP address of the host to check in dotted decimal format: AAA.BBB.CCC.DDD 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Test-NaExportFS -Pathname /vol/vol1 -Permission root -IPAddress 192.168.1.5
		
		Return $True if 192.168.1.5 had root permission on /vol/vol1
	.Link
		Get-NaExportfs
		New-NaExportfs
		Set-NaExportfs
		Remove-NaExportfs
		Update-NaExportfs
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Pathname,

	[Parameter(Mandatory=$True,Position=1,ValueFromPipelineByPropertyName=$TRUE)]
	[ValidateSet("ReadOnly", "ReadWrite", "Root")]
	[string]
	$Permission,

	[Parameter(Mandatory=$True,Position=2,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$IPAddress,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-check-permission")
		$request.AddNewChild("pathname",$Pathname)
		$request.AddNewChild("host",$IPAddress)
		switch ($Permission) {
			"ReadOnly" {$request.AddNewChild("permission","read-only")}
			"ReadWrite" {$request.AddNewChild("permission","read-write")}
			"Root" {$request.AddNewChild("permission","root")}
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			continue;
		}
		if ($?) {
			Convertfrom-NaBool $result."is-permissible"
		}
	}
}

function Enable-NaExportfsFence {
	<#
	.SYNOPSIS
		Enables fencing to the given exports for the given entry.
	.DESCRIPTION
		Enables fencing to the given exports for the given entry. This means that 
		the entry will not have write permission to the exports. The rule changes 
		take effect immediately. Set the persistent option to true to save the rule 
		in the /etc/exports file and keep the option persistent upon loading or reboot.
	.PARAMETER Pathname
		Paths which are to be fenced off. 
	.PARAMETER Hosts
		Hostnames which are to be fenced off.
	.PARAMETER Persistent
		If Present, modify the etc/exports file to append the rule for a permanent 
		change. (The new rule still takes effect immediately.) If not present, only 
		change the exports in memory. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Enable-NaExportfsFence -Hosts 192.168.1.1/26 -Pathname /vol/vol1/data
		
	.EXAMPLE
		Enable-NaExportfsFence -Hosts 192.168.1.1/26 -AllPaths
		
	.EXAMPLE
		Enable-NaExportfsFence -Pathname /vol/vol1/data -AllHosts
	
	.EXAMPLE
		Enable-NaExportfsFence -AllPaths -AllHosts
		
	.Link
		Disable-NaExportfsFence
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="ByPathAndHost")] 
	param(
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByPathAndHost")]
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByPath")]
	[string[]]
	$Pathname,

	[Parameter(Mandatory=$True,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByPathAndHost")]
	[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByHost")]
	[string[]]
	$Hosts,
	
	[Parameter(Mandatory=$True,ParameterSetName="all")]
	[Parameter(Mandatory=$true,ParameterSetName="ByHost")]
	[switch]
	$AllPaths,
	
	[Parameter(Mandatory=$True,ParameterSetName="all")]
	[Parameter(Mandatory=$true,ParameterSetName="ByPath")]
	[switch]
	$AllHosts,

	[Parameter()]
	[switch]
	$Persistent,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-fence-enable")
		$msg = ''
		if ($Persistent) {
			$request.AddNewChild("persistent", $True)
			$msg = "Perminatly,"
		}
		switch ($pscmdlet.ParameterSetName) {
			"byPath" 
			{
				$fencedPaths = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-paths")
				foreach ($p in $Pathname) {
					$pathnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("pathname-info")
					$pathnameInfo.AddNewChild("name",$P)
					$fencedPaths.AddChildElement($pathnameInfo)
				}
				$request.AddChildElement($fencedPaths)
				$msg = "{0} Fencing all writes from All Hosts on paths:'{1}'" -f $msg, ($pathname -join ", ")
				
				#by path infers fence all hosts on given path add all hosts.
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				$exportsHostnameInfo.AddNewChild("all-hosts",$true)
				$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
				$fencedHosts.AddChildElement($exportsHostnameInfo)
				$request.AddChildElement($fencedHosts)
				if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server -Persistent
							}
						} else {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server 
							}
						}
					}
				}
				
			}
			"ByHost" 
			{
				$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
				foreach ($h in $Hosts) {
					$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
					$exportsHostnameInfo.AddNewChild("name",$h)
					$fencedHosts.AddChildElement($exportsHostnameInfo)
				}
				$request.AddChildElement($fencedHosts)
				$msg = "{0} Fencing all writes from Hosts:'{1}' on ALL Paths" -f $msg, ($Hosts -join ", ")
				
				#byhosts infers all paths for given host add all paths.
				$request.AddNewChild("all-pathnames", $True)
				if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
								Get-NaExportfs -Server $Server -Persistent
						} else {
								Get-NaExportfs -Server $Server 
						}
					}
				}
			}
			"all" 
			{
				if ($PScmdlet.shouldcontinue("Are you sure you want to fence ALL PATHS on ALL HOSTS?","Potential loss of service")) {
					$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
					$exportsHostnameInfo.AddNewChild("all-hosts",$true)
					$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
					$fencedHosts.AddChildElement($exportsHostnameInfo)
					$request.AddChildElement($fencedHosts)
					$request.AddNewChild("all-pathnames", $True)
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
							Get-NaExportfs -Server $Server -Persistent
						} else {
							Get-NaExportfs -Server $Server 
						}
					}
				} else {
					break
				}
			}
			"ByPathAndHost"
			{
				#Add paths
				$fencedPaths = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-paths")
				foreach ($p in $Pathname) {
					$pathnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("pathname-info")
					$pathnameInfo.AddNewChild("name",$P)
					$fencedPaths.AddChildElement($pathnameInfo)
				}
				$request.AddChildElement($fencedPaths)
				
				#add hosts
				$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
				foreach ($h in $Hosts) {
					$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
					$exportsHostnameInfo.AddNewChild("name",$h)
					$fencedHosts.AddChildElement($exportsHostnameInfo)
				}
				$request.AddChildElement($fencedHosts)
				$msg = "{0} Fencing all writes from Hosts:'{1}' on Paths:'{2}'" -f $msg, ($Hosts -join ", "), ($Pathname -join ", ")
				if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server -Persistent
							}
						} else {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server 
							}
						}
					}
				}
			}
		}
	}
}
function Disable-NaExportfsFence {
	<#
	.SYNOPSIS
		Disables fencing to the given exports for the given entry. 
	.DESCRIPTION
		Disables fencing to the given exports for the given entry. This means that 
		the entry will have write permission to the exports. The rule changes take 
		effect immediately. Set the persistent option to save the rule in the 
		/etc/exports file and keep the option persistent upon loading or reboot. 
	.PARAMETER Pathname
		Paths which are to be fenced off. 
	.PARAMETER Hosts
		Hostnames which are to be fenced off.
	.PARAMETER RemoveLocks
		Set to true to reclaim locks of the specified fenced-hosts. 
	.PARAMETER AllPathnames
		Fence all rules
	.PARAMETER Persistent
		If Present, modify the etc/exports file to append the rule for a permanent 
		change. (The new rule still takes effect immediately.) If not present, only 
		change the exports in memory. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Disable-NaExportfsFence
	.Link
		Enable-NaExportfsFence
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByPathAndHost")]
	[Parameter(Mandatory=$True,Position=0,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByPath")]
	[string[]]
	$Pathname,

	[Parameter(Mandatory=$True,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByPathAndHost")]
	[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ByHost")]
	[string[]]
	$Hosts,
	
	[Parameter(Mandatory=$True,ParameterSetName="all")]
	[Parameter(Mandatory=$true,ParameterSetName="ByHost")]
	[switch]
	$AllPaths,
	
	[Parameter(Mandatory=$True,ParameterSetName="all")]
	[Parameter(Mandatory=$true,ParameterSetName="ByPath")]
	[switch]
	$AllHosts,
	
	[Parameter()]
	[switch]
	$RemoveLocks,

	[Parameter()]
	[switch]
	$Persistent,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-fence-disable")
		$msg = 'Removing '
		if ($Persistent) {
			$request.AddNewChild("persistent", $True)
			$msg = "Perminatly, Removing"
		}
		if ($RemoveLocks) {
			$request.AddNewChild("remove-locks", $True)
		}
		switch ($pscmdlet.ParameterSetName) {
			"byPath" 
			{
				$fencedPaths = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-paths")
				foreach ($p in $Pathname) {
					$pathnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("pathname-info")
					$pathnameInfo.AddNewChild("name",$P)
					$fencedPaths.AddChildElement($pathnameInfo)
				}
				$request.AddChildElement($fencedPaths)
				$msg = "{0} Fencing all writes from All Hosts on paths:'{1}'" -f $msg, ($pathname -join ", ")
				
				#by path infers fence all hosts on given path add all hosts.
				$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
				$exportsHostnameInfo.AddNewChild("all-hosts",$true)
				$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
				$fencedHosts.AddChildElement($exportsHostnameInfo)
				$request.AddChildElement($fencedHosts)
				if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server -Persistent
							}
						} else {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server 
							}
						}
					}
				}
				
			}
			"ByHost" 
			{
				$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
				foreach ($h in $Hosts) {
					$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
					$exportsHostnameInfo.AddNewChild("name",$h)
					$fencedHosts.AddChildElement($exportsHostnameInfo)
				}
				$request.AddChildElement($fencedHosts)
				$msg = "{0} Fencing all writes from Hosts:'{1}' on ALL Paths" -f $msg, ($Hosts -join ", ")
				
				#byhosts infers all paths for given host add all paths.
				$request.AddNewChild("all-pathnames", $True)
				if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
								Get-NaExportfs -Server $Server -Persistent
						} else {
								Get-NaExportfs -Server $Server 
						}
					}
				}
			}
			"all" 
			{
				if ($PScmdlet.shouldcontinue("Are you sure you want to fence ALL PATHS on ALL HOSTS?","Potential loss of service")) {
					$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
					$exportsHostnameInfo.AddNewChild("all-hosts",$true)
					$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
					$fencedHosts.AddChildElement($exportsHostnameInfo)
					$request.AddChildElement($fencedHosts)
					$request.AddNewChild("all-pathnames", $True)
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
							Get-NaExportfs -Server $Server -Persistent
						} else {
							Get-NaExportfs -Server $Server 
						}
					}
				} else {
					break
				}
			}
			"ByPathAndHost"
			{
				#Add paths
				$fencedPaths = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-paths")
				foreach ($p in $Pathname) {
					$pathnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("pathname-info")
					$pathnameInfo.AddNewChild("name",$P)
					$fencedPaths.AddChildElement($pathnameInfo)
				}
				$request.AddChildElement($fencedPaths)
				
				#add hosts
				$fencedHosts = New-Object Netapp.Manage.NaElement -ArgumentList @("fenced-hosts")
				foreach ($h in $Hosts) {
					$exportsHostnameInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("exports-hostname-info")
					$exportsHostnameInfo.AddNewChild("name",$h)
					$fencedHosts.AddChildElement($exportsHostnameInfo)
				}
				$request.AddChildElement($fencedHosts)
				$msg = "{0} Fencing all writes from Hosts:'{1}' on Paths:'{2}'" -f $msg, ($Hosts -join ", "), ($Pathname -join ", ")
				if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
					if ($?) {
						if ($Persistent) {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server -Persistent
							}
						} else {
							$pathname |%{
								Get-NaExportfs -Pathname $_ -Server $Server 
							}
						}
					}
				}
			}
		}
	}
}
function Remove-NaExportfsCache {
	<#
	.SYNOPSIS
		For the given path, renew or flush the access cache.
	.DESCRIPTION
		For the given path, renew or flush the access cache. 
	.PARAMETER Pathname
		Pathname to flush. If this input is not provided, all of the paths in the exports table are flushed.  
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Remove-NaExportfsCache
		
		Flush the access cache for all exports
	.Link
		Get-NaNFS
		Enable-NaExportfsFence
		Disable-NaExportfsFence
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
	[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE)]
	[string]
	$Pathname,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer]
	$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-exportfs-flush-cache")
		if ($Pathname) { 
			$request.AddNewChild("pathname",$Pathname)
			$msg = "Flushing the access cache for $($Pathname)"
		} else {
			$msg = "Flushing the access cache for All Paths"
		}
		if ($pscmdlet.ShouldProcess($Server.Server, $msg)){
			try {
				$server.InvokeElem($request)|Out-Null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}

function Get-NaNFSMonitor {
	<#
	.SYNOPSIS
		Lists the hosts that are currently being monitored by the NFS status monitor. 
	.DESCRIPTION
		Lists the hosts that are currently being monitored by the NFS status monitor. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Get-NaNFSMonitor
		
		Get the status of the NFS Service.
	.OUTPUT
		string[]
	.Link
		Set-NaNFSMonitor
		Add-NaNFSMonitor
		Remove-NaNFSMonitor
		UnLock-NaNFSMonitor
	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-monitor-list")
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?) {
			$result.Hosts | 
				#Where-Object {$_.hastaddr} |
				Select-Object @{
					Name="name"
					Expression={$_.hostaddr}
				}
		}
	}
}
function Add-NaNFSMonitor {
	<#
	.SYNOPSIS
		Starts monitoring the specified hosts for NFS lock recovery purposes. 
	.DESCRIPTION
		Starts monitoring the specified hosts for NFS lock recovery purposes. The 
		specified hosts are added to the list of of clients that will be notified 
		of lock recovery in the event of an NFS server crash/reboot. For more 
		information, see the sm_mon(1a) manual page
	.PARAMETER name
		hosts that are to be monitored. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Add-NaNFSMonitor -Name 192.168.1.25
		
		Add 192.168.1.25 to the list of monitored systems.
	.OUTPUT
		object[]
	.Link
		Get-NaNFSMonitor
		Set-NaNFSMonitor
		Remove-NaNFSMonitor
		UnLock-NaNFSMonitor
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Name,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-monitor-add")
		$hosts = New-Object Netapp.Manage.NaElement -ArgumentList @("hosts")
		foreach ($h in $name) {
			$Hosts.AddNewChild("hostaddr",$H)
		}
		$request.AddChildElement($hosts)
		if ($PScmdlet.ShouldProcess($Server.Server,"Add $($Name -join ', ') to the list of monitord systems.")) {
			try {
				[xml]$server.InvokeElem($request) | Out-Null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?) {
				Get-NaNFSMonitor -server $Server
			}
		}
	}
}
function Remove-NaNFSMonitor {
	<#
	.SYNOPSIS
		Starts unmonitoring the specified hosts for NFS lock recovery purposes. 
	.DESCRIPTION
		Starts unmonitoring the specified hosts for NFS lock recovery purposes. The 
		specified hosts are removed to the list of of clients that will be notified 
		of lock recovery in the event of an NFS server crash/reboot. For more 
		information, see the sm_mon(1a) manual page
	.PARAMETER name
		hosts that are to be monitored. 
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Remove-NaNFSMonitor -Name 192.168.1.25
		
		Remove 192.168.1.25 to the list of unmonitoring systems.
	.OUTPUT
		object[]
	.Link
		Get-NaNFSMonitor
		Set-NaNFSMonitor
		Add-NaNFSMonitor
		UnLock-NaNFSMonitor
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Name,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-monitor-remove")
		$hosts = New-Object Netapp.Manage.NaElement -ArgumentList @("hosts")
		foreach ($h in $hosts) {
			$Hosts.AddNewChild("hostaddr",$H)
		}
		$request.AddChildElement($hosts)
		if ($PScmdlet.ShouldProcess($Server.Server,"Remove $($Name -join ', ') from the list of monitord systems.")) {
			try {
				[xml]$server.InvokeElem($request) | Out-Null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?) {
				Get-NaNFSMonitor -server $Server
			}
		}
	}
}
function Set-NaNFSMonitor {
	<#
	.SYNOPSIS
		Reclaims the NFS locks for the specified client hosts.
	.DESCRIPTION
		Reclaims the NFS locks for the specified client hosts. If no hosts are 
		specified, then all the clients locks are removed and are notified about 
		lock recovery, as if an NFS server crash/reboot had happened. If any hosts 
		are specified, then only those client hosts locks are reclaimed For more 
		information, see the sm_mon(1a) manual page. 
	.PARAMETER Name
		Hosts whose locks have to be reclaimed. If no hosts are specified, then all 
		the clients locks are reclaimed.  
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		Set-NaNFSMonitor -Name 192.168.1.25
	.OUTPUT
		object[]
	.Link
		Get-NaNFSMonitor
		Add-NaNFSMonitor
		Remove-NaNFSMonitor
		UnLock-NaNFSMonitor
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE)]
		[string[]]
		$Name,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-monitor-reclaim")
		$hosts = New-Object Netapp.Manage.NaElement -ArgumentList @("hosts")
		foreach ($h in $hosts) {
			$Hosts.AddNewChild("hostaddr",$H)
		}
		$request.AddChildElement($hosts)
		if ($PScmdlet.ShouldProcess($Server.Server,"Reclaim NFS locks for $($Name -join ', ')")) {
			try {
				[xml]$server.InvokeElem($request) | Out-Null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
		}
	}
}
function UnLock-NaNFSMonitor {
	<#
	.SYNOPSIS
		Removes the NFS locks of a specfied process of a specified client host.  
	.DESCRIPTION
		Removes the NFS locks of a specfied process of a specified client host.  
	.PARAMETER Hostname
		Client host on which the locks have to be removed. 
	.PARAMETER PID
		Process owner on the above client host whose locks have to be removed.
	.PARAMETER Server
		NaServer to query
	.EXAMPLE
		UnLock-NaNFSMonitor -Hostname 192.168.1.25 -PID 1022
	.Link
		Get-NaNFSMonitor
		Set-NaNFSMonitor
		Add-NaNFSMonitor
		Remove-NaNFSMonitor
	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] 
	param(
		[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$Hostname,
		
		[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$TRUE)]
		[string]
		$PID,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$Server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("nfs-monitor-remove-locks")
		$owners = New-Object Netapp.Manage.NaElement -ArgumentList @("owners")
		$ownerInfo = New-Object Netapp.Manage.NaElement -ArgumentList @("owner-info")
		$ownerInfo.AddNewChild("client-host",$Hostname)
		$ownerInfo.AddNewChild("client-host-pid",$PID)
		$owners.AddChildElement($ownerInfo)
		$request.AddChildElement($owners)
		if ($PScmdlet.ShouldProcess($Server.Server,"Remove NFS Lock from $($Hostname):$($PID)")) {
			try {
				[xml]$server.InvokeElem($request) | Out-Null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
